select *
from tab;

-- [42000][923] ORA-00923: 未找到要求的 FROM 关键字 Position: 1
-- select 1+1;

/*
 oracle 要求 select 语句必须指定 from table
 如果仅仅是 简单的运算，不是查询某张表，此时可以用 dual 表来代替
 */
select 1 + 1
from dual;

select *
from DUAL;

select *
from USER_TAB_COLUMNS;

create table tab_2
(
    t1 int,
    t2 varchar(10),
    t3 float
);


insert into tab_2 (t1, t2, t3)
values (1, 'h1h1', 11);

select *
from tab_2;

-- 查看当前用户所有的表
select *
from tab;
-- 查询当前用户指定下的表的所有列，表名必须大写
select *
from USER_TAB_COLUMNS
where TABLE_NAME = 'TAB_2';


--  当只写一个表名时，默认是本用户的表
-- [42000][942] ORA-00942: 表或视图不存在 Position: 14
select *
from tab_2;

-- 想使用别人的表，必须加上用户名，且有访问权限

select *
from miao.tab_2;


select *
from TAB_2;

--  伪列1 rowid
-- [42000][923] ORA-00923: 未找到要求的 FROM 关键字 Position: 8  获取伪列需要给表起个别名
select *, ROWID, ROWNUM
from tab_2;

select t.*, t.rowid, ROWNUM
from TAB_2 t;
-- rowid AAASNsAAGAAAAALAAA  记录的本行数据的物理地址

-- 通过主键查询某行，需要对指定表对应的文件进行扫描
select *
from TAB_2
where T1 = 1;
-- 通过 rowid 查询某行，可以精准定义行数据的位置，不需要扫描效率高
select *
from TAB_2
where ROWID = 'AAASNsAAGAAAAALAAA';


drop table TAB_2;

create table tab_2
(
    t1 timestamp,
    t2 varchar(10),
    t3 float
);

insert into TAB_2 (t1, t2, t3)
values (sysdate, 'h1h1', 1);

/**
  伪列2 ROWNUM
  存在意义 实现 oracle 的分页
  获取结果集以后，自动给结果集添加的行号，从 1 开始
 */

select t.*, ROWNUM
from tab_2 t;

-- 每页 3 行，第一页
select t.*, ROWNUM
from tab_2 t
where ROWNUM <= 3;

-- 每页 3 行，第二页 无法实现
select t.*, ROWNUM
from tab_2 t
where ROWNUM >= 4
  and ROWNUM <= 6;

-- 通过子查询实现分页
select *
from (select t1, t2, t3, ROWNUM r from tab_2) t
where t.r >= 4
  and t.r <= 6;

-- 效率高一点的写法
select *
from (select t1, t2, t3, ROWNUM r from tab_2 where ROWNUM <= 6) t
where t.r >= 4;


/**
  1.4 dml 的不同之处  insert update delete
 */
/*
 删除行记录 delete 和 truncate
 */
delete
from tab_2;

truncate table tab_2;
/**
 delete 和 truncate 区别
  相同：delete 和 truncate 都可以用于删除表记录
  不同：1、delete 是 dml（数据操作：insert、update、delete 对表记录的增删改） 需要提交事务
       2、truncate 是 ddl(数据定义 对表结构的增删改）不需要提交事务

        1、delete 后面可以加指定条件，删除指定行
        2、truncate 后面不能加条件，只能删除所有记录

        1、truncate 效率高于 delete
 */

/**
  ddl : check 约束
 */
create table tab_3
(
    tid  int,
    tage int,
    check ( tage > 0 and tage < 100 )
);

-- [23000][2290] ORA-02290: 违反检查约束条件 (MIAO.SYS_C0011121) Position: 0
insert into tab_3 (tid, tage)
values (1, 101);


create table tab_4
(
    tid  int,
    tage int check ( tage > 0 and tage < 100 )
);
-- [23000][2290] ORA-02290: 违反检查约束条件 (MIAO.SYS_C0011123) Position: 0
insert into tab_4 (tid, tage)
values (1, 101);


/**
  复习约束
  1、唯一约束 unique
  2、非空约束  not null
  3、主键约束 primary Key
    * 特点1 唯一
    * 特点2 不为空
    * 特点3 可以被从表的外键引用
  4、默认约束 default
  5、检查约束 check
  6、外键约束 foreign key
    * 特点1 可以空
    * 特点2 可以重复
    * 特点3 一旦有值，此值必须在主键的主键列中存在
 */

drop table tab_5;

create table tab_5
(
    tid int primary key -- 定义表是指定主键
);

create table tab_5
(
    tid int,
    primary key (tid) -- 定义表时，指定主键
);


create table tab_5
(
    tid int
);
-- 创建表后 添加主键约束
alter table tab_5
    add primary key (tid);

-- 删除主键约束
alter table tab_5
    drop primary key;

-- 获取创建表的语句
select DBMS_METADATA.GET_DDL('TABLE', 'TAB_5')
from DUAL;

-- 查看指定表的所有约束
select a.constraint_name, a.COLUMN_NAME, a.*, b.*
from USER_CONS_COLUMNS a,
     USER_CONS_COLUMNS b
where a.CONSTRAINT_NAME = b.CONSTRAINT_NAME
  and a.TABLE_NAME = 'TAB_5';


drop table tab_6;

create table tab_6
(
    t5id int,
    -- 定义表的时候指定外键约束
    constraint fk_1 foreign key (t5id) references tab_5 (tid)
);

create table tab_6
(
    -- 定义表时指定外键约束
    t5id int references tab_5 (tid)
);

create table tab_6
(
    t5id int
);
-- 创建表之后添加外键约束
alter table tab_6
    add constraint fk_1 foreign key (t5id) references tab_5 (tid);

alter table tab_6
    modify t5id int references tab_5 (tid);

create table tab_7
(
    tid   int,
    tname varchar(10),
    tage  int
);

insert into tab_7 (tid, tname, tage)
values (1, '韩梅梅', 11);
insert into tab_7 (tid, tname, tage)
values (1, '韩梅梅', 11);
insert into tab_7 (tid, tname, tage)
values (1, '韩梅梅', 11);

create table tab_8
(
    tid   int,
    tname varchar(10)
);

-- 把查询的结果插入到指定的表中
insert into tab_8(tid, tname)
    (select tid, tname
     from tab_7);
select *
from tab_8;


/**
  dql
 */
drop table teacher;
drop table student;

create table teacher
(
    tid     int primary key,
    tname   varchar(20),
    tage    int,
    tsalary float
);

create table student
(
    sid   int primary key,
    sname varchar(20),
    sage  int,
    score float,
    stid  int references teacher (tid)
);


-- 插入数据
insert into teacher
values (1, '王老师', 32, 10000);
insert into teacher
values (2, '高老师', 31, 10010);
insert into student
values (1001, '张三1', 19, 23.5, 1);
insert into student
values (1002, '张三2', 18, 13.5, 1);
insert into student
values (1003, '张三3', 17, 33.5, 1);
insert into student
values (2001, '张三4', 16, 43.5, 2);
insert into student
values (2002, '张三5', 15, 53.5, 2);


/*合并结果集：获取所有师生的名字 编号 年龄 要求两个select的列数相同 列类型必须一直*/
select sid as 编号, sname as 姓名, sage as 年龄
from student
union
select tid, tname, tage
from teacher;

select sid 编号, sname 姓名, sage 年龄
from student
union all
select tid, tname, tage
from teacher;


/* 联合查询：获取所有老师及其学生的信息 */
select *
from student s
         right join teacher t on t.tid = s.stid;

/* oracle的外连接方言：：(+) 保证另外一张表的完整性 */
select *
from student s,
     teacher t
where t.tid(+) = s.stid;
/* 子查询：获取最低分学生的信息 */
select *
from student
where score = (select min(score) from student);
/* 获取最低分学生及其老师的信息 */
select *
from student s,
     teacher t
where s.stid = t.tid
  and s.score = (select min(score) from student);


/*
 序列 sequence
 */
--  创建序列
create sequence s_1;

-- 获取序列 s_1 的下一个值
select s_1.nextval
from DUAL;

-- 获取序列 s_1 的当前值
select s_1.currval
from DUAL;


insert into student(sid, sname)
values (s_1.nextval, '哈哈');

-- 同一个 sql 语句中， nextval 只加一次
select s_1.nextval, s_1.nextval, s_1.currval
from DUAL;

-- 字符串 concat 拼接
insert into student (sid, sname)
values (s_1.nextval, concat('哈哈', s_1.currval));

select *
from student;

-- 删除序列
drop sequence s_2;


create sequence s_2
    start with 10 -- 指定起始值，默认值是1
    increment by 2 -- 指定每次加的步长 默认值1
    maxvalue 30 -- 指定最大值
    minvalue 10 -- 循环时的最小值
    cycle -- cycle 循环  nocycle 不循环
    cache 4; -- 缓存个数，为了减少对数据库的访问，每次取出4个放在缓存中，默认20

select s_2.nextval
from DUAL;



/*
 索引 index
 */

-- 查询指定表有那些索引及其列
select *
from USER_IND_COLUMNS
where TABLE_NAME = 'STUDENT';

/*
索引分类： 唯一性索引：有unique约束的列 自动创建唯一性索引 非唯一性索引： 程序员自己创建的index 建议对列创建索引的情况 1 字段经常出现在where条件后面 2 查询的结果集行数<表总行数的4% 3 字段的值不能频繁修改 4 字段不能有大量null值 5 字段的值分布广*/

create table tab_11
(
    tid   int primary key,
    tname varchar(20) unique,
    tage  int,
    tsex  char(2)
);

select *
from USER_IND_COLUMNS
where TABLE_NAME = 'TAB_11';

-- 创建索引
create index ind_1 on tab_11 (tage);

-- 删除索引
drop index ind_1;


/**
  视图：view --结果集

  视图存在的意义：简化sql语句的书写
  作用：简化sql书写 (降低数据库的复杂度) 对敏感数据的保护
 */

--  创建视图
create view v_1 as
select sid, sname, sage
from student;

-- 视图的使用基本和表一样
select *
from v_1;
-- 查看当前用户的所有视图
select *
from USER_VIEWS;

insert into v_1 (sid, sname, sage)
values (201, '呵呵', 91);


/*可以通过view对基表进行增删改 但必须满足一些条件

--不能违反基表的约束

--视图对应的select语句不能包含 集合函数、分组、distinct 等操作

--视图中不能包含伪列和表达式等
  */


/**
  事务
 */
drop table bank_account;

create table bank_account
(
    bid    int primary key,
    bname  varchar(20),
    bmoney float check ( bmoney >= 0 )
);

create sequence seq_ba
    start with 1000;



insert into bank_account
values (seq_ba.nextval, '张 三', 500);
insert into bank_account
values (seq_ba.nextval, '李 四', 1000);


-- 需要 在 Services 窗口中，设置 Enable DBMSOUTPUT, 才能显示信息
begin
    update bank_account set bmoney=bmoney + 100 where bname = '李四';
    update bank_account set bmoney=bmoney - 100 where bname = '张三';
    commit;
    dbms_output.put_line('转账成功!');
exception
    when others then
        dbms_output.put_line('转账失败!');
        rollback;
end;


